  <!DOCTYPE html>
  <html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="generator" content="pandoc" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
    <title>GTK 4 tutorial</title>
    <style>
      code{white-space: pre-wrap;}
      span.smallcaps{font-variant: small-caps;}
      span.underline{text-decoration: underline;}
      div.column{display: inline-block; vertical-align: top; width: 50%;}
      div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
      ul.task-list{list-style: none;}
      pre{overflow: visible;}
      pre > code.sourceCode { white-space: pre; position: relative; }
      pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
      pre > code.sourceCode > span:empty { height: 1.2em; }
      code.sourceCode > span { color: inherit; text-decoration: inherit; }
      div.sourceCode { margin: 1em 0; }
      pre.sourceCode { margin: 0; }
      @media screen {
      div.sourceCode { overflow: auto; }
      }
      @media print {
      pre > code.sourceCode { white-space: pre-wrap; }
      pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
      }
      pre.numberSource code
        { counter-reset: source-line 0; }
      pre.numberSource code > span
        { position: relative; left: -4em; counter-increment: source-line; }
      pre.numberSource code > span > a:first-child::after
        { content: counter(source-line);
          position: relative; left: -1em; text-align: right; vertical-align: baseline;
          border: none; display: inline-block;
          -webkit-touch-callout: none; -webkit-user-select: none;
          -khtml-user-select: none; -moz-user-select: none;
          -ms-user-select: none; user-select: none;
          padding: 0 4px; width: 4em;
          color: #aaaaaa;
        }
      pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }
      div.sourceCode
        {   }
      @media screen {
      pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
      }
      code span.al { color: #ff0000; font-weight: bold; } /* Alert */
      code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
      code span.at { color: #7d9029; } /* Attribute */
      code span.bn { color: #40a070; } /* BaseN */
      code span.bu { } /* BuiltIn */
      code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
      code span.ch { color: #4070a0; } /* Char */
      code span.cn { color: #880000; } /* Constant */
      code span.co { color: #60a0b0; font-style: italic; } /* Comment */
      code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
      code span.do { color: #ba2121; font-style: italic; } /* Documentation */
      code span.dt { color: #902000; } /* DataType */
      code span.dv { color: #40a070; } /* DecVal */
      code span.er { color: #ff0000; font-weight: bold; } /* Error */
      code span.ex { } /* Extension */
      code span.fl { color: #40a070; } /* Float */
      code span.fu { color: #06287e; } /* Function */
      code span.im { } /* Import */
      code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
      code span.kw { color: #007020; font-weight: bold; } /* Keyword */
      code span.op { color: #666666; } /* Operator */
      code span.ot { color: #007020; } /* Other */
      code span.pp { color: #bc7a00; } /* Preprocessor */
      code span.sc { color: #4070a0; } /* SpecialChar */
      code span.ss { color: #bb6688; } /* SpecialString */
      code span.st { color: #4070a0; } /* String */
      code span.va { color: #19177c; } /* Variable */
      code span.vs { color: #4070a0; } /* VerbatimString */
      code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
      div.sourceCode { margin: 10px; padding: 16px 10px 8px 10px; border: 2px solid silver; background-color: ghostwhite; overflow-x:scroll}
      pre:not(.sourceCode) { margin: 10px; padding: 16px 10px 8px 10px; border: 2px solid silver; background-color: ghostwhite; overflow-x:scroll}
      table {margin-left: auto; margin-right: auto; border-collapse: collapse; border: 1px solid;}
      th {padding: 2px 6px; border: 1px solid; background-color: ghostwhite;}
      td {padding: 2px 6px; border: 1px solid;}
      img {display: block; margin-left: auto; margin-right: auto;}
      figcaption {text-align: center;}
    </style>
  </head>
  <body style="padding-top: 70px;">
    <div class="container">
    <nav class="navbar fixed-top navbar-expand-lg navbar-dark bg-primary">
      <div class="container-fluid">
        <span class="navbar-brand">Gtk4 tutorial</span>
        <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
          <span class="navbar-toggler-icon"></span>
        </button>
        <div class="collapse navbar-collapse" id="navbarSupportedContent">
          <ul class="navbar-nav me-auto mb-2 mb-lg-0">
            <li class="nav-item">
<a class="nav-link" href="index.html">Home</a>
</li>

            <li class="nav-item">
<a class="nav-link" href="sec26.html">Prev: section26</a>
</li>

            <li class="nav-item">
<a class="nav-link" href="sec28.html">Next: section28</a>
</li>

          </ul>
        </div>
      </div>
    </nav>
<h1 id="gtkgridview-and-activate-signal">GtkGridView and activate
signal</h1>
<p>GtkGridView is similar to GtkListView. It displays a GListModel as a
grid, which is like a square tessellation.</p>
<figure>
<img src="image/list4.png" alt="Grid" />
<figcaption aria-hidden="true">Grid</figcaption>
</figure>
<p>This is often seen when you use a file browser like GNOME Files
(Nautilus).</p>
<p>In this section, let’s make a very simple file browser
<code>list4</code>. It just shows the files in the current directory.
And a user can choose list or grid by clicking on buttons in the tool
bar. Each item in the list or grid has an icon and a filename. In
addition, <code>list4</code> provides the way to open the
<code>tfe</code> text editor to show a text file. A user can do that by
double clicking on an item or pressing enter key when an item is
selected.</p>
<h2 id="gtkdirectorylist">GtkDirectoryList</h2>
<p>GtkDirectoryList implements GListModel and it contains information of
files in a certain directory. The items of the list are GFileInfo
objects.</p>
<p>In the <code>list4</code> source files, GtkDirectoryList is described
in a ui file and built by GtkBuilder. The GtkDirectoryList instance is
assigned to the “model” property of a GtkSingleSelection instance. And
the GtkSingleSelection instance is assigned to the “model” property of a
GListView or GGridView instance.</p>
<pre><code>GtkListView (model property) =&gt; GtkSingleSelection (model property) =&gt; GtkDirectoryList
GtkGridView (model property) =&gt; GtkSingleSelection (model property) =&gt; GtkDirectoryList</code></pre>
<figure>
<img src="image/directorylist.png" alt="DirectoryList" />
<figcaption aria-hidden="true">DirectoryList</figcaption>
</figure>
<p>The following is a part of the ui file <code>list4.ui</code>.</p>
<div class="sourceCode" id="cb2"><pre
class="sourceCode xml"><code class="sourceCode xml"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a>&lt;<span class="kw">object</span><span class="ot"> class=</span><span class="st">&quot;GtkListView&quot;</span><span class="ot"> id=</span><span class="st">&quot;list&quot;</span>&gt;</span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>  &lt;<span class="kw">property</span><span class="ot"> name=</span><span class="st">&quot;model&quot;</span>&gt;</span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>    &lt;<span class="kw">object</span><span class="ot"> class=</span><span class="st">&quot;GtkSingleSelection&quot;</span><span class="ot"> id=</span><span class="st">&quot;singleselection&quot;</span>&gt;</span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>      &lt;<span class="kw">property</span><span class="ot"> name=</span><span class="st">&quot;model&quot;</span>&gt;</span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>        &lt;<span class="kw">object</span><span class="ot"> class=</span><span class="st">&quot;GtkDirectoryList&quot;</span><span class="ot"> id=</span><span class="st">&quot;directorylist&quot;</span>&gt;</span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>          &lt;<span class="kw">property</span><span class="ot"> name=</span><span class="st">&quot;attributes&quot;</span>&gt;standard::name,standard::icon,standard::content-type&lt;/<span class="kw">property</span>&gt;</span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>        &lt;/<span class="kw">object</span>&gt;</span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a>      &lt;/<span class="kw">property</span>&gt;</span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a>    &lt;/<span class="kw">object</span>&gt;</span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a>  &lt;/<span class="kw">property</span>&gt;</span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a>&lt;/<span class="kw">object</span>&gt;</span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a>&lt;<span class="kw">object</span><span class="ot"> class=</span><span class="st">&quot;GtkGridView&quot;</span><span class="ot"> id=</span><span class="st">&quot;grid&quot;</span>&gt;</span>
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true" tabindex="-1"></a>  &lt;<span class="kw">property</span><span class="ot"> name=</span><span class="st">&quot;model&quot;</span>&gt;singleselection&lt;/<span class="kw">property</span>&gt;</span>
<span id="cb2-14"><a href="#cb2-14" aria-hidden="true" tabindex="-1"></a>&lt;/<span class="kw">object</span>&gt;</span></code></pre></div>
<p>GtkDirectoryList has an “attributes” property. It is attributes of
GFileInfo such as “standard::name”, “standard::icon” and
“standard::content-type”.</p>
<ul>
<li>standard::name is a filename.</li>
<li>standard::icon is an icon of the file. It is a GIcon object.</li>
<li>standard::content-type is a content-type. Content-type is the same
as mime type for the internet. For example, “text/plain” is a text file,
“text/x-csrc” is a C source code and so on. (“text/x-csrc”is not
registered to IANA media types. Such “x-” subtype is not a standard mime
type.) Content type is also used by desktop systems.</li>
</ul>
<p>GtkGridView uses the same GtkSingleSelection instance
(<code>singleselection</code>). So, its model property is set with
it.</p>
<h2 id="ui-file-of-the-window">Ui file of the window</h2>
<p>The window is built with the following ui file. (See the screenshot
at the beginning of this section).</p>
<p>@@<span class="citation" data-cites="include">@include</span>
list4/list4.ui @@@</p>
<p>The file consists of two parts. The first part begins at the line 3
and ends at line 57. This part is the widgets from the top level window
to the scrolled window. It also includes two buttons. The second part
begins at line 58 and ends at line 71. This is the part of GtkListView
and GtkGridView.</p>
<ul>
<li>13-17, 42-46: Two labels are dummy labels. They just work as a space
to put the two buttons at the appropriate position.</li>
<li>18-41: GtkButton <code>btnlist</code> and <code>btngrid</code>.
These two buttons work as selection buttons to switch from list to grid
and vice versa. These two buttons are connected to a stateful action
<code>win.view</code>. This action has a parameter. Such action consists
of prefix, action name and parameter. The prefix of the action is
<code>win</code>, which means the action belongs to the top level
window. The prefix gives the scope of the action. The action name is
<code>view</code>. The parameters are <code>list</code> or
<code>grid</code>, which show the state of the action. A parameter is
also called a target, because it is a target to which the action changes
its state. We often write the detailed action like “win.view::list” or
“win.view::grid”.</li>
<li>21-22: The properties “action-name” and “action-target” belong to
GtkActionable interface. GtkButton implements GtkActionable. The action
name is “win.view” and the target is “list”. Generally, a target is
GVariant, which can be string, integer, float and so on. You need to use
GVariant text format to write GVariant value in ui files. If the type of
the GVariant value is string, then the value with GVariant text format
is bounded by single quotes or double quotes. Because ui file is xml
format text, single quote cannot be written without escape. Its escape
sequence is &amp;apos;. Therefore, the target ‘list’ is written as
&amp;apos;list&amp;apos;. Because the button is connected to the action,
“clicked” signal handler isn’t needed.</li>
<li>23-27: The child widget of the button is GtkImage. GtkImage has a
“resource” property. It is a GResource and GtkImage reads an image data
from the resource and sets the image. This resource is built from
24x24-sized png image data, which is an original icon.</li>
<li>50-53: GtkScrolledWindow. Its child widget will be set with
GtkListView or GtkGridView.</li>
</ul>
<p>The action <code>view</code> is created, connected to the “activate”
signal handler and inserted to the window (action map) as follows.</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a>act_view <span class="op">=</span> g_simple_action_new_stateful <span class="op">(</span><span class="st">&quot;view&quot;</span><span class="op">,</span> g_variant_type_new<span class="op">(</span><span class="st">&quot;s&quot;</span><span class="op">),</span> g_variant_new_string <span class="op">(</span><span class="st">&quot;list&quot;</span><span class="op">));</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>g_signal_connect <span class="op">(</span>act_view<span class="op">,</span> <span class="st">&quot;activate&quot;</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>view_activated<span class="op">),</span> NULL<span class="op">);</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>g_action_map_add_action <span class="op">(</span>G_ACTION_MAP <span class="op">(</span>win<span class="op">),</span> G_ACTION <span class="op">(</span>act_view<span class="op">));</span></span></code></pre></div>
<p>The signal handler <code>view_activated</code> will be explained
later.</p>
<h2 id="factories">Factories</h2>
<p>Each view (GtkListView and GtkGridView) has its own factory because
its items have different structure of widgets. The factories are
GtkBuilderListItemFactory objects. Their ui files are as follows.</p>
<p>factory_list.ui</p>
<p>@@<span class="citation" data-cites="include">@include</span>
list4/factory_list.ui @@@</p>
<p>factory_grid.ui</p>
<p>@@<span class="citation" data-cites="include">@include</span>
list4/factory_grid.ui @@@</p>
<p>The two files above are almost same. The difference is:</p>
<ul>
<li>The orientation of the box</li>
<li>The icon size</li>
<li>The position of the text of the label</li>
</ul>
<p>@@<span class="citation" data-cites="shell">@shell</span> cd list4;
diff factory_list.ui factory_grid.ui @@@</p>
<p>Two properties “gicon” (property of GtkImage) and “label” (property
of GtkLabel) are in the ui files above. Because GFileInfo doesn’t have
properties correspond to icon or filename, the factory uses closure tag
to bind “gicon” and “label” properties to GFileInfo information. A
function <code>get_icon</code> gets GIcon from the GFileInfo object. And
a function <code>get_file_name</code> gets a filename from the GFileInfo
object.</p>
<p>@@<span class="citation" data-cites="include">@include</span>
list4/list4.c get_icon get_file_name @@@</p>
<p>One important thing is the ownership of the return values. The return
value is owned by the caller. So, <code>g_obect_ref</code> or
<code>g_strdup</code> is necessary.</p>
<h2 id="an-activate-signal-handler-of-the-button-action">An activate
signal handler of the button action</h2>
<p>An activate signal handler <code>view_activate</code> switches the
view. It does two things.</p>
<ul>
<li>Changes the child widget of GtkScrolledWindow.</li>
<li>Changes the CSS of buttons to show the current state.</li>
</ul>
<p>@@<span class="citation" data-cites="include">@include</span>
list4/list4.c view_activated @@@</p>
<p>The second parameter of this handler is the target of the clicked
button. Its type is GVariant.</p>
<ul>
<li>If <code>btnlist</code> has been clicked, then
<code>parameter</code> is a GVariant of the string “list”.</li>
<li>If <code>btngrid</code> has been clicked, then
<code>parameter</code> is a GVariant of the string “grid”.</li>
</ul>
<p>The third parameter <code>user_data</code> points NULL and it is
ignored here.</p>
<ul>
<li>3: <code>g_variant_get_string</code> gets the string from the
GVariant variable.</li>
<li>7-13: Sets the child of <code>scr</code>. The function
<code>gtk_scrolled_window_set_child</code> decreases the reference count
of the old child by one. And it increases the reference count of the new
child by one.</li>
<li>14-16: Sets the CSS for the buttons. The background of the clicked
button will be silver color and the other button will be white.</li>
<li>17: Changes the state of the action.</li>
</ul>
<h2 id="activate-signal-on-gtklistview-and-gtkgridview">Activate signal
on GtkListView and GtkGridView</h2>
<p>Views (GtkListView and GtkGridView) have an “activate” signal. It is
emitted when an item in the view is double clicked or the enter key is
pressed. You can do anything you like by connecting the “activate”
signal to the handler.</p>
<p>The example <code>list4</code> launches <code>tfe</code> text file
editor if the item of the list is a text file.</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="dt">static</span> <span class="dt">void</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>list_activate <span class="op">(</span>GtkListView <span class="op">*</span>list<span class="op">,</span> <span class="dt">int</span> position<span class="op">,</span> gpointer user_data<span class="op">)</span> <span class="op">{</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>  GFileInfo <span class="op">*</span>info <span class="op">=</span> G_FILE_INFO <span class="op">(</span>g_list_model_get_item <span class="op">(</span>G_LIST_MODEL <span class="op">(</span>gtk_list_view_get_model <span class="op">(</span>list<span class="op">)),</span> position<span class="op">));</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>  launch_tfe_with_file <span class="op">(</span>info<span class="op">);</span></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a><span class="dt">static</span> <span class="dt">void</span></span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a>grid_activate <span class="op">(</span>GtkGridView <span class="op">*</span>grid<span class="op">,</span> <span class="dt">int</span> position<span class="op">,</span> gpointer user_data<span class="op">)</span> <span class="op">{</span></span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a>  GFileInfo <span class="op">*</span>info <span class="op">=</span> G_FILE_INFO <span class="op">(</span>g_list_model_get_item <span class="op">(</span>G_LIST_MODEL <span class="op">(</span>gtk_grid_view_get_model <span class="op">(</span>grid<span class="op">)),</span> position<span class="op">));</span></span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a>  launch_tfe_with_file <span class="op">(</span>info<span class="op">);</span></span>
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb4-12"><a href="#cb4-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-13"><a href="#cb4-13" aria-hidden="true" tabindex="-1"></a><span class="op">...</span> <span class="op">...</span></span>
<span id="cb4-14"><a href="#cb4-14" aria-hidden="true" tabindex="-1"></a><span class="op">...</span> <span class="op">...</span></span>
<span id="cb4-15"><a href="#cb4-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-16"><a href="#cb4-16" aria-hidden="true" tabindex="-1"></a>  g_signal_connect <span class="op">(</span>GTK_LIST_VIEW <span class="op">(</span>list<span class="op">),</span> <span class="st">&quot;activate&quot;</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>list_activate<span class="op">),</span> NULL<span class="op">);</span></span>
<span id="cb4-17"><a href="#cb4-17" aria-hidden="true" tabindex="-1"></a>  g_signal_connect <span class="op">(</span>GTK_GRID_VIEW <span class="op">(</span>grid<span class="op">),</span> <span class="st">&quot;activate&quot;</span><span class="op">,</span> G_CALLBACK <span class="op">(</span>grid_activate<span class="op">),</span> NULL<span class="op">);</span></span></code></pre></div>
<p>The second parameter of each handler is the position of the item
(GFileInfo) of the GListModel. So you can get the item with
<code>g_list_model_get_item</code> function.</p>
<h3 id="content-type-and-application-launch">Content type and
application launch</h3>
<p>The function <code>launch_tfe_with_file</code> gets a file from the
GFileInfo instance. If the file is a text file, it launches
<code>tfe</code> with the file.</p>
<p>GFileInfo has information about file type. The file type is like
“text/plain”, “text/x-csrc” and so on. It is called content type.
Content type can be got with <code>g_file_info_get_content_type</code>
function.</p>
<p>@@<span class="citation" data-cites="include">@include</span>
list4/list4.c launch_tfe_with_file @@@</p>
<ul>
<li>13: Gets the content type of the file from GFileInfo.</li>
<li>14-16: Prints the content type if “debug” is defined. This is only
useful to know a content type of a file. If you don’t want this, delete
or uncomment the definition <code>#define debug 1</code> iat line 6 in
the source file.</li>
<li>17-22: If no content type or the content type doesn’t begin with
“text/”,the function returns.</li>
<li>23: Creates GAppInfo object of <code>tfe</code> application.
GAppInfo is an interface and the variable <code>appinfo</code> points a
GDesktopAppInfo instance. GAppInfo is a collection of information of
applications.</li>
<li>32: Launches the application (<code>tfe</code>) with an argument
<code>file</code>. <code>g_app_info_launch</code> has four parameters.
The first parameter is GAppInfo object. The second parameter is a list
of GFile objects. In this function, only one GFile instance is given to
<code>tfe</code>, but you can give more arguments. The third parameter
is GAppLaunchContext, but this program gives NULL instead. The last
parameter is the pointer to the pointer to a GError.</li>
<li>36: <code>g_list_free_full</code> frees the memories used by the
list and items.</li>
</ul>
<p>If your distribution supports GTK 4, using
<code>g_app_info_launch_default_for_uri</code> is convenient. The
function automatically determines the default application from the file
and launches it. For example, if the file is text, then it launches
gedit with the file. Such feature comes from desktop.</p>
<h2 id="compilation-and-execution">Compilation and execution</h2>
<p>The source files are located in src/list4 directory. To compile and
execute list4, type as follows.</p>
<pre><code>$ cd list4 # or cd src/list4. It depends your current directory.
$ meson _build
$ ninja -C _build
$ _build/list4</code></pre>
<p>Then a file list appears as a list style. Click on a button on the
tool bar so that you can change the style to grid or back to list.
Double click “list4.c” item, then <code>tfe</code> text editor runs with
the argument “list4.c”. The following is the screenshot.</p>
<figure>
<img src="image/screenshot_list4.png" alt="Screenshot" />
<figcaption aria-hidden="true">Screenshot</figcaption>
</figure>
<h2 id="gbytes-property-of-gtkbuilderlistitemfactory">“gbytes” property
of GtkBuilderListItemFactory</h2>
<p>GtkBuilderListItemFactory has “gbytes” property. The property
contains a byte sequence of ui data. If you use this property, you can
put the contents of <code>factory_list.ui</code> and
<code>factory_grid.ui</code>into <code>list4.ui</code>. The following
shows a part of the new ui file (<code>list5.ui</code>).</p>
<div class="sourceCode" id="cb6"><pre
class="sourceCode xml"><code class="sourceCode xml"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a>  &lt;<span class="kw">object</span><span class="ot"> class=</span><span class="st">&quot;GtkListView&quot;</span><span class="ot"> id=</span><span class="st">&quot;list&quot;</span>&gt;</span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>    &lt;<span class="kw">property</span><span class="ot"> name=</span><span class="st">&quot;model&quot;</span>&gt;</span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a>      &lt;<span class="kw">object</span><span class="ot"> class=</span><span class="st">&quot;GtkSingleSelection&quot;</span><span class="ot"> id=</span><span class="st">&quot;singleselection&quot;</span>&gt;</span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a>        &lt;<span class="kw">property</span><span class="ot"> name=</span><span class="st">&quot;model&quot;</span>&gt;</span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a>          &lt;<span class="kw">object</span><span class="ot"> class=</span><span class="st">&quot;GtkDirectoryList&quot;</span><span class="ot"> id=</span><span class="st">&quot;directory_list&quot;</span>&gt;</span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a>            &lt;<span class="kw">property</span><span class="ot"> name=</span><span class="st">&quot;attributes&quot;</span>&gt;standard::name,standard::icon,standard::content-type&lt;/<span class="kw">property</span>&gt;</span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a>          &lt;/<span class="kw">object</span>&gt;</span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a>        &lt;/<span class="kw">property</span>&gt;</span>
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true" tabindex="-1"></a>      &lt;/<span class="kw">object</span>&gt;</span>
<span id="cb6-10"><a href="#cb6-10" aria-hidden="true" tabindex="-1"></a>    &lt;/<span class="kw">property</span>&gt;</span>
<span id="cb6-11"><a href="#cb6-11" aria-hidden="true" tabindex="-1"></a>    &lt;<span class="kw">property</span><span class="ot"> name=</span><span class="st">&quot;factory&quot;</span>&gt;</span>
<span id="cb6-12"><a href="#cb6-12" aria-hidden="true" tabindex="-1"></a>      &lt;<span class="kw">object</span><span class="ot"> class=</span><span class="st">&quot;GtkBuilderListItemFactory&quot;</span>&gt;</span>
<span id="cb6-13"><a href="#cb6-13" aria-hidden="true" tabindex="-1"></a>        &lt;<span class="kw">property</span><span class="ot"> name=</span><span class="st">&quot;bytes&quot;</span>&gt;<span class="bn">&lt;![CDATA[</span></span>
<span id="cb6-14"><a href="#cb6-14" aria-hidden="true" tabindex="-1"></a>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</span>
<span id="cb6-15"><a href="#cb6-15" aria-hidden="true" tabindex="-1"></a>&lt;interface&gt;</span>
<span id="cb6-16"><a href="#cb6-16" aria-hidden="true" tabindex="-1"></a>  &lt;template class=&quot;GtkListItem&quot;&gt;</span>
<span id="cb6-17"><a href="#cb6-17" aria-hidden="true" tabindex="-1"></a>    &lt;property name=&quot;child&quot;&gt;</span>
<span id="cb6-18"><a href="#cb6-18" aria-hidden="true" tabindex="-1"></a>      &lt;object class=&quot;GtkBox&quot;&gt;</span>
<span id="cb6-19"><a href="#cb6-19" aria-hidden="true" tabindex="-1"></a>        &lt;property name=&quot;orientation&quot;&gt;GTK_ORIENTATION_HORIZONTAL&lt;/property&gt;</span>
<span id="cb6-20"><a href="#cb6-20" aria-hidden="true" tabindex="-1"></a>        &lt;property name=&quot;spacing&quot;&gt;20&lt;/property&gt;</span>
<span id="cb6-21"><a href="#cb6-21" aria-hidden="true" tabindex="-1"></a>        &lt;child&gt;</span>
<span id="cb6-22"><a href="#cb6-22" aria-hidden="true" tabindex="-1"></a>          &lt;object class=&quot;GtkImage&quot;&gt;</span>
<span id="cb6-23"><a href="#cb6-23" aria-hidden="true" tabindex="-1"></a>            &lt;binding name=&quot;gicon&quot;&gt;</span>
<span id="cb6-24"><a href="#cb6-24" aria-hidden="true" tabindex="-1"></a>              &lt;closure type=&quot;GIcon&quot; function=&quot;get_icon&quot;&gt;</span>
<span id="cb6-25"><a href="#cb6-25" aria-hidden="true" tabindex="-1"></a>                &lt;lookup name=&quot;item&quot;&gt;GtkListItem&lt;/lookup&gt;</span>
<span id="cb6-26"><a href="#cb6-26" aria-hidden="true" tabindex="-1"></a>              &lt;/closure&gt;</span>
<span id="cb6-27"><a href="#cb6-27" aria-hidden="true" tabindex="-1"></a>            &lt;/binding&gt;</span>
<span id="cb6-28"><a href="#cb6-28" aria-hidden="true" tabindex="-1"></a>          &lt;/object&gt;</span>
<span id="cb6-29"><a href="#cb6-29" aria-hidden="true" tabindex="-1"></a>        &lt;/child&gt;</span>
<span id="cb6-30"><a href="#cb6-30" aria-hidden="true" tabindex="-1"></a>        &lt;child&gt;</span>
<span id="cb6-31"><a href="#cb6-31" aria-hidden="true" tabindex="-1"></a>          &lt;object class=&quot;GtkLabel&quot;&gt;</span>
<span id="cb6-32"><a href="#cb6-32" aria-hidden="true" tabindex="-1"></a>            &lt;property name=&quot;hexpand&quot;&gt;TRUE&lt;/property&gt;</span>
<span id="cb6-33"><a href="#cb6-33" aria-hidden="true" tabindex="-1"></a>            &lt;property name=&quot;xalign&quot;&gt;0&lt;/property&gt;</span>
<span id="cb6-34"><a href="#cb6-34" aria-hidden="true" tabindex="-1"></a>            &lt;binding name=&quot;label&quot;&gt;</span>
<span id="cb6-35"><a href="#cb6-35" aria-hidden="true" tabindex="-1"></a>              &lt;closure type=&quot;gchararray&quot; function=&quot;get_file_name&quot;&gt;</span>
<span id="cb6-36"><a href="#cb6-36" aria-hidden="true" tabindex="-1"></a>                &lt;lookup name=&quot;item&quot;&gt;GtkListItem&lt;/lookup&gt;</span>
<span id="cb6-37"><a href="#cb6-37" aria-hidden="true" tabindex="-1"></a>              &lt;/closure&gt;</span>
<span id="cb6-38"><a href="#cb6-38" aria-hidden="true" tabindex="-1"></a>            &lt;/binding&gt;</span>
<span id="cb6-39"><a href="#cb6-39" aria-hidden="true" tabindex="-1"></a>          &lt;/object&gt;</span>
<span id="cb6-40"><a href="#cb6-40" aria-hidden="true" tabindex="-1"></a>        &lt;/child&gt;</span>
<span id="cb6-41"><a href="#cb6-41" aria-hidden="true" tabindex="-1"></a>      &lt;/object&gt;</span>
<span id="cb6-42"><a href="#cb6-42" aria-hidden="true" tabindex="-1"></a>    &lt;/property&gt;</span>
<span id="cb6-43"><a href="#cb6-43" aria-hidden="true" tabindex="-1"></a>  &lt;/template&gt;</span>
<span id="cb6-44"><a href="#cb6-44" aria-hidden="true" tabindex="-1"></a>&lt;/interface&gt;</span>
<span id="cb6-45"><a href="#cb6-45" aria-hidden="true" tabindex="-1"></a>        <span class="bn">]]&gt;</span>&lt;/<span class="kw">property</span>&gt;</span>
<span id="cb6-46"><a href="#cb6-46" aria-hidden="true" tabindex="-1"></a>      &lt;/<span class="kw">object</span>&gt;</span>
<span id="cb6-47"><a href="#cb6-47" aria-hidden="true" tabindex="-1"></a>    &lt;/<span class="kw">property</span>&gt;</span>
<span id="cb6-48"><a href="#cb6-48" aria-hidden="true" tabindex="-1"></a>  &lt;/<span class="kw">object</span>&gt;</span></code></pre></div>
<p>CDATA section begins with “&lt;[CDATA[” and ends with ”]]&gt;”. The
contents of CDATA section is recognized as a string. Any character, even
if it is a key syntax marker such as ‘&lt;’ or ‘&gt;’, is recognized
literally. Therefore, the text between “&lt;[CDATA[” and ”]]&gt;” is
inserted to “bytes” property as it is.</p>
<p>This method decreases the number of ui files. But, the new ui file is
a bit complicated especially for the beginners. If you feel some
difficulty, it is better for you to separate the ui file.</p>
<p>A directory src/list5 includes the ui file above.</p>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
  </body>
  </html>
